home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacGofer 0.22d / MacGofer Sources / mac_scroll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-06  |  7.2 KB  |  333 lines  |  [TEXT/MPS ]

  1. /*****************************************************************************
  2.  
  3.   mac_scroll.c:  Copyright (c) Kevin Hammond 1993.   All rights reserved.
  4.   
  5.       Routines to handle window scroll bars -- only the front window
  6.       may be scrolled in this way.
  7.  
  8. *****************************************************************************/
  9.  
  10.  
  11. #include "mac.h"
  12.  
  13. #pragma segment Scroll
  14.  
  15. #define HORIZ_SCALE    10        /* scale factor to speed horizontal scrolling */
  16.  
  17. #define InactiveScroll    255
  18. #define ActiveScroll    0
  19.  
  20.  
  21. pascal void ScrollText(ControlHandle scrollbar, short thePart);
  22.  
  23. static Boolean vscroll = TRUE;          /* Whether scrolling vertically or horizontally */
  24.  
  25.  
  26.  
  27. /*
  28.     Scroll a window according to whether the thumb bar's been hit, 
  29.     the current point and whether we're scrolling vertically or 
  30.     horizontally.
  31. */
  32.  
  33. DoScroll(thePart,thePoint,vertical)
  34. short thePart;
  35. Point thePoint;
  36. short vertical;
  37. {
  38.   if(isLegalWindow(thefrontwindow))
  39.     {
  40.       ControlHandle scrollbar = vertical? VSCROLL(thefrontwindow):
  41.                                           HSCROLL(thefrontwindow);
  42.   
  43.       if(thePart == inThumb)
  44.         {
  45.           thePart = TrackControl(scrollbar,thePoint,(ProcPtr)NIL);
  46.           AdjustText(thefrontwindow);
  47.         }
  48.       else if (thePart != 0)
  49.         {
  50.       vscroll = vertical;
  51.           thePart = TrackControl(scrollbar,thePoint,(ProcPtr)ScrollText);
  52.     }
  53.     }
  54. }
  55.  
  56.  
  57.  
  58. /*
  59.     Scroll vertically.
  60. */
  61.  
  62. void ScrollVText(scrollbar,vertical,thePart)
  63. ControlHandle scrollbar;
  64. short thePart;
  65. Boolean vertical;
  66. {
  67.   vscroll = vertical;
  68.   ScrollText(scrollbar,thePart);
  69. }
  70.  
  71.  
  72. /*
  73.     Handle a scrolling motion for the scroll bar, and adjust
  74.     the text to suit.  Called from within an autotracking
  75.     routine, so vscroll needs to be set outside this to
  76.     indicate whether we're scrolling vertically or horizontally.
  77. */
  78.  
  79. pascal void ScrollText(scrollbar,thePart)
  80. ControlHandle scrollbar;
  81. short thePart;
  82. {
  83.   
  84.   if(isLegalWindow(thefrontwindow))
  85.     {
  86.       short delta = 0;
  87.       Rect vr;
  88.       
  89.       TEHLock(thefrontwindow);
  90.       
  91.       vr = (*TEHANDLE(thefrontwindow))->viewRect;
  92.  
  93.       switch(thePart)
  94.         {
  95.       case inUpButton:
  96.         delta = -1;
  97.         break;
  98.  
  99.       case inDownButton:
  100.         delta = 1;
  101.         break;
  102.  
  103.           case inPageUp:
  104.         if(vscroll)
  105.           delta = (vr.top-vr.bottom)/(*TEHANDLE(thefrontwindow))->lineHeight -1;
  106.         else
  107.           delta = (vr.left-vr.right)/HORIZ_SCALE - 1;
  108.         break;
  109.         
  110.        case inPageDown:
  111.         if(vscroll)
  112.           delta = (vr.bottom-vr.top)/(*TEHANDLE(thefrontwindow))->lineHeight -1;
  113.         else
  114.           delta = (vr.right-vr.left)/HORIZ_SCALE - 1;
  115.         break;
  116.       }
  117.     
  118.     TEHUnlock(thefrontwindow);
  119.       
  120.     if(thePart!=0 && delta != 0)
  121.       {
  122.         short old = GetCtlValue(scrollbar);
  123.         short new = old+delta;
  124.         short max;
  125.         
  126.         if(new <= 1)
  127.           SetCtlValue(scrollbar,1);
  128.  
  129.         else if(new >= (max = GetCtlMax(scrollbar)))
  130.           {
  131.             if( old < max )
  132.               SetCtlValue(scrollbar,max);
  133.           }
  134.  
  135.         else
  136.           SetCtlValue(scrollbar,old+delta);
  137.  
  138.         AdjustText(thefrontwindow);
  139.       }
  140.     }
  141. }
  142.  
  143.  
  144.  
  145. /*
  146.     Scroll the text in the window to match the positions of the
  147.     scroll bars.
  148. */
  149.  
  150. AdjustText(windex)
  151. int windex;
  152. {
  153.   if(isLegalWindow(windex))
  154.     {
  155.       short old, new;
  156.   
  157.       TEHandle teh = TEHANDLE(windex);
  158.       
  159.       /* vertical scroll bars */
  160.       old = (*teh)->viewRect.top - (*teh)->destRect.top;
  161.       new = (GetCtlValue(VSCROLL(windex))-1)*(*teh)->lineHeight;
  162.       TEScroll(0,old-new,teh);
  163.      
  164.       /* horizontal scroll bars */
  165.       old = (*teh)->viewRect.left - (*teh)->destRect.left;
  166.       new = (GetCtlValue(HSCROLL(windex))-1)*HORIZ_SCALE;
  167.       TEScroll(old-new,0,teh);
  168.     }
  169. }
  170.  
  171.  
  172.  
  173. /* 
  174.    Set the scroll bars correctly.
  175.    This version prevents Gofer from scrolling up when the first character 
  176.    is typed and the cursor's at the bottom of the window.
  177. */
  178.  
  179.  
  180. AdjustScrollBars(windex)
  181. int windex;
  182. {
  183.   if(isLegalWindow(windex))
  184.     {
  185.       TEPtr teptr = *TEHANDLE(windex);
  186.  
  187.       Rect vr = teptr->viewRect;
  188.       Rect dr = teptr->destRect;
  189.  
  190.       short lineHeight =   teptr->lineHeight;
  191.       short windowHeight = (vr.bottom-vr.top)/lineHeight;
  192.       short windowWidth =  (vr.right-vr.left);
  193.  
  194.       /* We need an extra line if the last character is a newline */
  195.       Boolean extraLineNeeded = *( *teptr->hText + (teptr->teLength - 1) ) == '\n';
  196.       short maxHeight = teptr->nLines + (extraLineNeeded ? 2 : 1) - windowHeight;
  197.       short maxWidth = (dr.right - dr.left - windowWidth)/HORIZ_SCALE+2;
  198.       
  199.       setcontrolmax(VSCROLL(windex),maxHeight);
  200.       setcontrolmax(HSCROLL(windex),maxWidth);
  201.     }
  202. }
  203.  
  204.  
  205. /*
  206.     Set a new maximum value for a control.
  207.     If this is one, deactivate the control.
  208. */
  209.  
  210. setcontrolmax(control,value)
  211. ControlHandle control;
  212. short value;
  213. {
  214.   if(value <= 1)
  215.     {
  216.       value = 1;
  217.       HiliteControl(control,InactiveScroll);
  218.     }
  219.   else
  220.     HiliteControl(control,ActiveScroll);
  221.  
  222.   SetCtlMax(control,value);
  223. }
  224.  
  225.  
  226. /*
  227.     The routine which is called automatically when the
  228.     mouse is down in the scrollbar.
  229. */
  230.  
  231. pascal Boolean AutoScroll()
  232. {
  233.   if(isLegalWindow(thefrontwindow))
  234.     {
  235.       Point mousePt;
  236.       Rect tempRect;
  237.       
  238.       RgnHandle saveClip = NewRgn();
  239.       
  240.       GetClip(saveClip);
  241.       ClipRect(&(WINDOW(thefrontwindow)->portRect));
  242.       GetMouse(&mousePt);
  243.       tempRect = (*TEHANDLE(thefrontwindow))->viewRect;
  244.  
  245.       if(mousePt.v < tempRect.top)
  246.         ScrollVText(VSCROLL(thefrontwindow),TRUE,inUpButton);
  247.  
  248.       else if(mousePt.v > tempRect.bottom)
  249.         ScrollVText(VSCROLL(thefrontwindow),TRUE,inDownButton);
  250.  
  251.       else if(mousePt.h < tempRect.left)
  252.         ScrollVText(HSCROLL(thefrontwindow),FALSE,inUpButton);
  253.  
  254.       else if(mousePt.h > tempRect.right)
  255.         ScrollVText(HSCROLL(thefrontwindow),FALSE,inDownButton);
  256.  
  257.       SetClip(saveClip);
  258.       DisposeRgn(saveClip);
  259.     }
  260.   return(TRUE);
  261. }
  262.  
  263.  
  264. /*
  265.     Scroll a window to the character whose position is given.
  266.     If tobottom is set, then we are scrolling downwards, so
  267.     it is acceptable to scroll one position past the maximum.
  268. */
  269.  
  270. ScrollCharacter(windex,posn,tobottom)
  271. int windex;
  272. short posn;
  273. Boolean tobottom;
  274. {
  275.   if(isLegalWindow(windex))
  276.     {
  277.        TEHandle teh = TEHANDLE(windex);
  278.        short i;
  279.  
  280.        /* find line start corresponding to posn */
  281.        for(i=1;(*teh)->lineStarts[i]<posn;++i)
  282.          ;
  283.  
  284.        /* Allow for character at start of line */   
  285.        if(i < (*teh)->nLines && (*teh)->lineStarts[i]==posn)
  286.          ++i;
  287.  
  288.        if(tobottom)
  289.          {
  290.        short max = GetCtlMax(VSCROLL(windex));
  291.        if( i > max)
  292.          i = max+1;
  293.         }
  294.  
  295.        SetCtlValue(VSCROLL(windex),i-1);
  296.        AdjustText(windex);
  297.      }
  298. }
  299.  
  300.  
  301. /*
  302.     Scroll the window so the current selection is on screen, if this
  303.     isn't currently the case.
  304. */
  305.  
  306. ScrollToSelection(windex)
  307. int windex;
  308. {
  309.   if(isLegalWindow(windex))
  310.     {
  311.       TEHandle teh = TEHANDLE(windex);
  312.       Rect vr;
  313.       short top, bottom, height, max;
  314.  
  315.       vr = (*teh)->viewRect;
  316.       
  317.       top = GetCtlValue(VSCROLL(windex))-1;
  318.       height = (vr.bottom-vr.top)/(*teh)->lineHeight;
  319.       bottom = top + height;
  320.       
  321.       max = GetCtlMax(VSCROLL(windex));
  322.             
  323.       if(max == 1)
  324.         AdjustText(windex);
  325.     
  326.       else if ((*teh)->selEnd < (*teh)->lineStarts[top])
  327.         ScrollCharacter(windex,(*teh)->selStart,FALSE);
  328.  
  329.       else if ((*teh)->selStart >= (*teh)->lineStarts[bottom])
  330.         ScrollCharacter(windex,(*teh)->selEnd,TRUE);
  331.     }
  332. }
  333.